package com.cskaoyan.javase.object._4hashcode;

/**
 * hashCode()方法的方法声明：
 * public native int hashCode();
 * 很显然，它是一个本地方法，这个方法也没有任何参数，返回值是一个int类型整数。
 *
 * 方法的作用(jdk文档中的原话):
 * 1. 返回该对象的哈希码值。
 * 2. 支持此方法是为了提高哈希表（例如 java.util.Hashtable 提供的哈希表）的性能。
 *
 * 在很多时候，我们都需要重写hashCode方法，JDK文档中给我们标注了重写的规则和什么时候进行重写，如下：
 * 1. 在 Java 应用程序执行期间，在对同一对象多次调用 hashCode 方法时，必须一致地返回相同的整数，前提是将对象进行 equals比较时所用的信息没有被修改。
 *
 * 2. 如果根据 `equals(Object)方法`，两个对象是相等的，那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。这是**因为equals是判断对象相等的，对象相等后，就相当于是集合A中的同一个元素，那么它们哈希映射的结果必然相同。**这是映射定义强制要求的。
 *
 * 3. 如果根据 `equals(java.lang.Object) `方法，两个对象不相等，那么对这两个对象中的任一对象上调用hashCode方法不要求一定生成不同的整数结果。但是，程序员应该意识到，为不相等的对象生成不同整数结果可以提高哈希表的性能。
 * 虽然完美是达不到的,但追求完美的心应该还是要有的
 *
 * 注意事项:
 * 1.一旦重写hashCode方法后，默认的toString方法就不会再打印地址值了。这是因为toString方法，默认调用的是本地方法的hashCode方法获取地址值，重写后不再是地址值了。
 * 2. 如果类中有引用数据类型成员变量，那么就继续调用它的hashCode方法，也就需要重写它的hashCode方法。
 *
 *
 * @since 10:55
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Teacher t1 = new Teacher(18, 10000, 8);
        Teacher t2 = new Teacher(18, 10000, 8);
        System.out.println(t1.hashCode());
        System.out.println(t2.hashCode());
        System.out.println(t1.equals(t2));

        System.out.println(t1);
        System.out.println(t2);

        /*System.out.println("----------------");

        Teacher t3 = t1;
        System.out.println(t3.hashCode());
        System.out.println(t1.hashCode());
        System.out.println(t1.equals(t3));*/
    }
}

class Teacher {
    int age;
    double salary;
    int touchFishTime;

    public Teacher() {
    }

    public Teacher(int age, double salary, int touchFishTime) {
        this.age = age;
        this.salary = salary;
        this.touchFishTime = touchFishTime;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Teacher teacher = (Teacher) o;

        if (age != teacher.age) return false;
        if (Double.compare(teacher.salary, salary) != 0) return false;
        return touchFishTime == teacher.touchFishTime;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        result = age;
        temp = Double.doubleToLongBits(salary);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        result = 31 * result + touchFishTime;
        return result;
    }
}